﻿using Mapster;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using Shipeng.Util;
using SqlSugar;
using System.ComponentModel.DataAnnotations;
using System.Linq.Expressions;
using Yitter.IdGenerator;
using YNTK.Common.Const;
using YNTK.Common.Enum;
using YNTK.Common.Filter;
using YNTK.Data.MongoDB.Repositorie;
using YNTK.Dependency;
using YNTK.DynamicApiController;
using YNTK.FileRecord.Entitys;
using YNTK.FileRecord.Interface;
using YNTK.FriendlyException;
using YNTK.LinqBuilder;
using YNTK.Mapster;
using YNTK.System.Entitys.Dto.Common;
using YNTK.System.Entitys.Permission;
using YNTK.System.Entitys.Resources;
using YNTK.System.Interfaces.Common;
using YNTK.System.Interfaces.Permission;
using YNTK.System.Interfaces.Resources;

namespace YNTK.FileRecord
{
    /// <summary>
    /// 文件清单/工作记录服务的实现
    /// 版 本：V1.0.0.0
    /// 版 权：云南通科科技有限公司（https://www.yntkkj.com）
    /// 作 者：李仕鹏
    /// 日 期：2022.10.26
    /// </summary>
    [ApiDescriptionSettings(Tag = "文件清单/工作记录服务", Name = "FileRecord", Order = 787)]
    [Route("api/[controller]")]
    public class FileRecordService: IFileRecordService, IDynamicApiController, ITransient
    {
        private readonly ISqlSugarRepository<FileInventoryEntity > _repository;//文件清单仓储
        private readonly IMongoDBRepository<FileInventoryEntity > _mongoDbRepository;//文件清单mongodb仓储
        private readonly ISqlSugarRepository<WorkRecordsEntity> _workRepository;//工作记录仓储
        private readonly IMongoDBRepository<WorkRecordsEntity> _workMongoDbRepository;//工作记录mongodb仓储
        private readonly ISqlSugarRepository<WorkRecordDynamicFieldsEntity> _dynamicRepository;//工作记录动态字段仓储
        private readonly IMongoDBRepository<WorkRecordDynamicFieldsEntity> _dynamicMongoDbRepository;//工作记录动态字段mongodb仓储
        private readonly ISqlSugarRepository<WorkRecordFilesEntity> _fileRepository;//工作记录相关附件仓储
        private readonly IMongoDBRepository<WorkRecordFilesEntity> _fileMongoDbRepository;//工作记录相关附件mongodb仓储

        private readonly ITkUsersService _tkUsersService;//用户服务
        private readonly IOrganizeService _organizeService;//组织服务
        private readonly IMechanismService _mechanismService;//机构服务
        private readonly IDictionaryService _dictionaryService;//字典服务
        private readonly IFileService _fileService;//文件服务
        private readonly ITkRoleService _tkRoleService;//角色服务
        private readonly HttpContext _httpContext;

        private readonly string _collection = "filerecord_fileslists";//mongodb中文件清单数据集名称
        private readonly string _work = "filerecord_workrecords";//mongodb中工作记录数据集名称
        private readonly string _dynamic = "filerecord_workrecords_dynamicfields";//mongodb中工作记录动态字段数据集名称
        private readonly string _files = "filerecord_workrecords_files";//mongodb中工作记录相关附件数据集名称

        /// <summary>
        /// 构造方法依赖注入
        /// </summary>
        /// <param name="repository">文件清单仓储</param>
        /// <param name="mongoDbRepository">文件清单mongodb仓储</param>
        /// <param name="workRepository">工作记录仓储</param>
        /// <param name="workMongoDbRepository">工作记录mongodb仓储</param>
        /// <param name="dynamicRepository">工作记录动态字段仓储</param>
        /// <param name="dynamicMongoDbRepository">工作记录动态字段mongodb仓储</param>
        /// <param name="fileRepository">工作记录相关附件仓储</param>
        /// <param name="fileMongoDbRepository">工作记录相关附件mongodb仓储</param>
        /// <param name="tkUsersService">用户服务</param>
        /// <param name="organizeService">组织服务</param>
        /// <param name="mechanismService">机构服务</param>
        /// <param name="dictionaryService">字典服务</param>
        /// <param name="fileService">文件服务</param>
        /// <param name="tkRoleService">角色服务</param>
        public FileRecordService(ISqlSugarRepository<FileInventoryEntity > repository,
            IMongoDBRepository<FileInventoryEntity > mongoDbRepository,
            ISqlSugarRepository<WorkRecordsEntity> workRepository,
            IMongoDBRepository<WorkRecordsEntity> workMongoDbRepository,
            ISqlSugarRepository<WorkRecordDynamicFieldsEntity> dynamicRepository,
            IMongoDBRepository<WorkRecordDynamicFieldsEntity> dynamicMongoDbRepository,
            ISqlSugarRepository<WorkRecordFilesEntity> fileRepository,
            IMongoDBRepository<WorkRecordFilesEntity> fileMongoDbRepository,
            ITkUsersService tkUsersService, IOrganizeService organizeService,
            IMechanismService mechanismService, IDictionaryService dictionaryService,
            IFileService fileService, ITkRoleService tkRoleService)
        {
            _repository = repository;
            _mongoDbRepository = mongoDbRepository;
            _workRepository = workRepository;
            _workMongoDbRepository = workMongoDbRepository;
            _dynamicRepository = dynamicRepository;
            _dynamicMongoDbRepository = dynamicMongoDbRepository;
            _fileRepository = fileRepository;
            _fileMongoDbRepository = fileMongoDbRepository;
            _tkUsersService = tkUsersService;
            _organizeService = organizeService;
            _mechanismService = mechanismService;
            _dictionaryService = dictionaryService;
            _fileService = fileService;
            _tkRoleService = tkRoleService;
            _httpContext = App.HttpContext;
        }

        #region 文件清单
        /// <summary>
        /// 获取文件清单分类工作项树结构数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("tree")]
        public async Task<TkResult<List<FileListTreeDto>>> GetTree()
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                //获取文件清单分类数据
                var classifys = await _dictionaryService.GetDictionaryListAsync(m=>m.OrganizeId== organizeId && 
                m.Type== DictionaryType.FileList.GetHashCode() && m.DeleteMark==null && m.EnabledMark==1);
                var treeList = new List<FileListTreeDto>();
                if (!classifys.Any()) return TkResult<List<FileListTreeDto>>.Success(treeList);

                //获取工作项/事项数据
                var classifyIds = classifys.Select(r => r.Id).ToList();
                var fileList = await GetFileInventoryListAsync(m=>m.OrganizeId== organizeId && m.DeleteMark==null && m.EnabledMark==1);
                //获取顶级分类(一级)
                var topData = classifys.Where(r => string.IsNullOrWhiteSpace(r.ParentId)).OrderBy(r=>r.SortCode).ToList();
                var entity = new FileListTreeDto();
                var files = new List<FileInventoryEntity>();
                string classifyId = "";
                topData.ForEach(top =>
                {
                    entity = new FileListTreeDto();
                    entity.type = 0;//类型(0.分类 1.工作项/事项)
                    entity.id = top.Id;                   
                    entity.parentId = top.ParentId;
                    classifyId = _dictionaryService.GetId(top.Id, classifys);
                    entity.classifyId = classifyId;//分类id
                    entity.classifyName = top.Name;//分类名称                   
                    files = fileList?.Where(r => r.ClassifyId == classifyId)?.OrderBy(r => r.SortCode)?.ToList();
                    entity.children = new List<FileListTreeDto>();
                    if (files!=null && files.Count>0)
                    {
                        files.ForEach(file =>
                        {
                            entity.children.Add(new FileListTreeDto()
                            {
                                type=1,//类型(0.分类 1.工作项/事项)
                                id=file.Id,
                                parentId=entity.id,
                                classifyId= classifyId,//分类id
                                classifyName= entity.classifyName,//分类名称
                                workItemId= file.Id,//工作项/事项id
                                workItem =file.WorkItem,//工作项/事项
                                code =file.Code,//编号
                                sampleFormFilePath =file.SampleFormFilePath,
                                sampleFormFileName=!string.IsNullOrWhiteSpace(file.SampleFormFilePath) &&
                                file.SampleFormFilePath.Contains("{@yntk@}") ? 
                                file.SampleFormFilePath.Split("{@yntk@}")[1] : ""
                            });
                        });
                    }
                    entity.children = GetChildren(entity.children, classifys, top.Id, fileList);
                    treeList.Add(entity);
                });
                return TkResult<List<FileListTreeDto>>.Success(treeList);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取文件清单分类工作项树结构数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 处理文件清单分类子级数据
        /// </summary>
        /// <param name="children">子级数据</param>
        /// <param name="classifys">文件清单分类数据</param>
        /// <param name="id">当前分类id</param>
        /// <param name="fileList">工作项数据</param>
        /// <returns></returns>
        private List<FileListTreeDto> GetChildren(List<FileListTreeDto> children, List<DictionaryEntity> classifys,
            string id, List<FileInventoryEntity> fileList)
        {
            //获取当前分类的子级分类数据
            var childrenData = classifys.Where(r => r.ParentId == id)?.OrderBy(r=>r.SortCode)?.ToList();
            if (childrenData!=null && childrenData.Count>0)
            {
                var entity = new FileListTreeDto();
                var files = new List<FileInventoryEntity>();
                string classifyId = "";
                childrenData.ForEach(node =>
                {
                    entity = new FileListTreeDto();
                    entity.type = 0;//类型(0.分类 1.工作项/事项)
                    entity.id = node.Id;
                    entity.parentId = node.ParentId;
                    classifyId = _dictionaryService.GetId(node.Id, classifys);
                    entity.classifyId = classifyId;//分类id
                    entity.classifyName = node.Name;//分类名称                   
                    files = fileList?.Where(r => r.ClassifyId == classifyId)?.OrderBy(r => r.SortCode)?.ToList();
                    entity.children = new List<FileListTreeDto>();
                    if (files != null && files.Count > 0)
                    {
                        files.ForEach(file =>
                        {
                            entity.children.Add(new FileListTreeDto()
                            {
                                type = 1,//类型(0.分类 1.工作项/事项)
                                id = file.Id,
                                parentId = entity.id,
                                classifyId = classifyId,//分类id
                                classifyName = entity.classifyName,//分类名称
                                workItemId = file.Id,//工作项/事项id
                                workItem = file.WorkItem,//工作项/事项
                                code = file.Code,//编号
                                sampleFormFilePath = file.SampleFormFilePath,
                                sampleFormFileName = !string.IsNullOrWhiteSpace(file.SampleFormFilePath) &&
                                file.SampleFormFilePath.Contains("{@yntk@}") ?
                                file.SampleFormFilePath.Split("{@yntk@}")[1] : ""
                            });
                        });
                    }
                    entity.children = GetChildren(entity.children, classifys, node.Id, fileList);
                    children.Add(entity);
                });
            }
            return children;
        }

        /// <summary>
        /// 分页获取文件清单数据
        /// </summary>
        /// <param name="query">查询文件清单请求模型</param>
        /// <returns></returns>
        [HttpPost("inventory/gets")]
        public async Task<TkPageResult<FileInventoryListDto>> GetFileInventoryList([FromBody] QueryFileInventoryFilterRequestModel query)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                #region 拼接查询条件
                Expression<Func<FileInventoryEntity, bool>> where = m =>
                m.OrganizeId == organizeId && m.DeleteMark == null;
                if (query.enabledMark == 1) where = where.And(m => m.EnabledMark == 1);
                if (query.enabledMark == 0) where = where.And(m => m.EnabledMark != 1);
                if (!string.IsNullOrWhiteSpace(query.mechanismId))
                {
                    string queryMechanismId = await _mechanismService.GetIdAsync(query.mechanismId, organizeId);
                    where = where.And(m => m.MechanismId == queryMechanismId);
                }
                if (!string.IsNullOrWhiteSpace(query.classifyId))
                {
                    string queryClassifyId = await _dictionaryService.GetIdAsync(query.classifyId, organizeId);
                    where = where.And(m => m.ClassifyId == queryClassifyId);
                }
                if (query.startTime != null) where = where.And(m => m.CreatorTime >= query.startTime);
                if (query.endTime != null) where = where.And(m => m.CreatorTime <= query.endTime);
                if (!string.IsNullOrWhiteSpace(query.keyword))
                    where = where.And(m => m.WorkItem.Contains(query.keyword) ||
                    m.Code.Contains(query.keyword) ||  m.Description.Contains(query.keyword));
                #endregion

                var pageList = new SqlSugarPagedList<FileInventoryListDto>();
                #region 先从mongodb中获取文件清单数据
                //排序生成器
                var builderSort = Builders<FileInventoryEntity>.Sort;
                //排序约束   Ascending 正序    Descending 倒序
                var sort = builderSort.Ascending(r => r.SortCode).Descending(r => r.CreatorTime);
                //Item1.结果集 Item2.总条数 Item3.总页数
                (List<FileInventoryEntity>, int, int) result =
                    await _mongoDbRepository.GetListAsync(_collection,
                    where, query.currentPage, query.pageSize, null, sort);
                pageList.list = result.Item1.Adapt<List<FileInventoryListDto>>();
                pageList.pagination = new PagedModel()
                {
                    PageIndex = query.currentPage,
                    PageSize = query.pageSize,
                    Total = result.Item2,
                    PageCount = result.Item3
                };
                #endregion

                if (pageList.list == null || pageList.list.Count() <= 0)
                {
                    #region 再从sqlserver中获取文件清单数据
                    var sqlResult = await _repository.Entities.Where(where)
                         .OrderBy(r => r.SortCode, OrderByType.Asc)
                         .OrderBy(r => r.CreatorTime, OrderByType.Desc)
                         .ToPagedListAsync(query.currentPage, query.pageSize);
                    pageList.list = sqlResult.list.Adapt<List<FileInventoryListDto>>();
                    pageList.pagination = sqlResult.pagination;
                    #endregion
                }

                #region 处理文件清单返回数据
                 if (pageList.list.Any())
                {
                    var orgIds = pageList.list.Select(r => r.organizeId).Distinct().ToList();
                    var orgs = await _organizeService.GetOrganizeListByIds(orgIds);
                    var mechanismIds = pageList.list.Where(r => !string.IsNullOrWhiteSpace(r.mechanismId))
                        ?.Select(r => r.mechanismId.Split(',').ToList())
                        ?.SelectMany(r => r).Distinct().ToList();
                    var mechanisms = !mechanismIds.Any() ? new List<MechanismEntity>() :
                        await _mechanismService.GetMechanismListAsync(null, mechanismIds);
                    var classifyIds = pageList.list.Select(r => r.classifyId.Split(',').ToList())
                       .SelectMany(r => r).Distinct().ToList();
                    var classifys = await _dictionaryService.GetDictionaryListByIds(classifyIds);
                    var userIds = pageList.list.Select(r => r.creatorUserId).Distinct().ToList();
                    var users = await _tkUsersService.GetUserListByIds(userIds);
                    pageList.list.ForEach(item =>
                    {
                        if (!string.IsNullOrWhiteSpace(item.organizeId))
                            item.organizeName = orgs?.FirstOrDefault(r => r.Id == item.organizeId)?.FullName;
                        if (!string.IsNullOrWhiteSpace(item.mechanismId))
                        {
                            item.mechanismName = string.Join('/', mechanisms
                                ?.Where(r => item.mechanismId.Split(',').ToList().Contains(r.Id))
                                ?.Select(r => r.Name)?.ToList());
                        }
                        if (!string.IsNullOrWhiteSpace(item.classifyId))
                        {
                            item.classifyName = string.Join('/', classifys
                                ?.Where(r => item.classifyId.Split(',').ToList().Contains(r.Id))
                                ?.Select(r => r.Name)?.ToList());
                        }
                        if (!string.IsNullOrWhiteSpace(item.sampleFormFilePath) && 
                        item.sampleFormFilePath.Contains("{@yntk@}"))
                            item.sampleFormFileName = item.sampleFormFilePath.Split("{@yntk@}")[1];
                        if (!string.IsNullOrWhiteSpace(item.creatorUserId))
                            item.creatorUserName = users?.FirstOrDefault(r => r.Id == item.creatorUserId)?.RealName;         
                    });
                }
                #endregion

                return TkPageResult<FileInventoryListDto>.Success(pageList);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"分页获取文件清单数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加文件清单
        /// </summary>
        /// <param name="input">添加文件清单请求模型</param>
        /// <returns></returns>
        [HttpPost("inventory/add")]
        public async Task AddFileInventory([FromBody] AddFileInventoryRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                if((await GetFileInventoryInfoAsync(r=>r.OrganizeId== organizeId && r.MechanismId== mechanismId && 
                r.WorkItem==input.workItem && r.DeleteMark==null))!=null) 
                    throw YNTKException.Oh(ErrorCode.Record0001);
                if ((await GetFileInventoryInfoAsync(r => r.OrganizeId == organizeId && r.MechanismId == mechanismId &&
                r.Code == input.code && r.DeleteMark == null)) != null)
                    throw YNTKException.Oh(ErrorCode.Record0025);

                var entity = input.Adapt<FileInventoryEntity>();
                entity.OrganizeId = organizeId;
                entity.MechanismId = mechanismId;

                //保存文件清单到sqlserver
                var isOk = await _repository.Context.Insertable(entity)
                    .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.Record0002);
                //保存文件清单到mongodb
                entity = isOk;
                var result = await _mongoDbRepository.AddAsync(entity, _collection);
                if (!result) throw YNTKException.Oh(ErrorCode.Record0003);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加文件清单发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改文件清单
        /// </summary>
        /// <param name="input">修改文件清单请求模型</param>
        /// <returns></returns>
        [HttpPut("inventory/update")]
        public async Task UpdateFileInventory([FromBody] UpdateFileInventoryRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetFileInventoryInfoAsync(r=>r.Id==input.id && r.DeleteMark==null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Record0004);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);
                if ((await GetFileInventoryInfoAsync(r => r.OrganizeId == organizeId && r.MechanismId == mechanismId &&
               r.WorkItem == input.workItem && r.Id!=input.id && r.DeleteMark == null)) != null)
                    throw YNTKException.Oh(ErrorCode.Record0001);
                if ((await GetFileInventoryInfoAsync(r => r.OrganizeId == organizeId && r.MechanismId == mechanismId &&
               r.Code == input.code && r.Id != input.id && r.DeleteMark == null)) != null)
                    throw YNTKException.Oh(ErrorCode.Record0025);

                entity = input.Mapper(entity);
                //保存文件清单到sqlserver
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;
                var isOK = await _repository.Context.Updateable(entity)
                .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Record0005);
                //保存文件清单到mongodb
                var update = await _mongoDbRepository.UpdateAsync(entity, _collection, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Record0006);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改文件清单发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除文件清单
        /// </summary>
        /// <param name="id">文件清单id</param>
        /// <returns></returns>
        [HttpDelete("inventory/delete/{id}")]
        public async Task DeleteFileInventory([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetFileInventoryInfoAsync(r => r.Id ==id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Record0004);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //先从sqlserver中删除
                var isOk = await _repository.Context.Deleteable(entity).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Record0007);
                //再从mongodb中删除
                var delete = await _mongoDbRepository.DeleteAsync(_collection,m=>m.Id==id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Record0008);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除文件清单发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新文件清单状态(启用/禁用)
        /// </summary>
        /// <param name="id">文件清单id</param>
        /// <returns></returns>
        [HttpPut("inventory/state/{id}")]
        public async Task UpdateFileInventoryState([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetFileInventoryInfoAsync(r => r.Id == id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Record0004);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //更新sqlserver中文件清单状态
                var isOk = await _repository.Context.Updateable<FileInventoryEntity>()
                .SetColumns(it => new FileInventoryEntity()
                {
                    EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1),
                    LastModifyUserId = userId,
                    LastModifyTime = SqlFunc.GetDate()
                }).Where(it => it.Id == id).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Record0009);
                //更新mongodb中文件清单状态
                entity.EnabledMark = entity.EnabledMark == 1 ? 0 : 1;
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;
                var update = await _mongoDbRepository.UpdateAsync(entity, _collection, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Record0010);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"更新文件清单状态(启用/禁用)发生异常：{ex.Message}");
            }
        }



        /// <summary>
        /// 根据条件获取文件清单数据
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<List<FileInventoryEntity>> GetFileInventoryListAsync(Expression<Func<FileInventoryEntity, bool>> where)
        {
            var result = await _mongoDbRepository.GetListAsync(_collection, where);
            if (!result.Any())
            {
                //再从sqlserver中获取
                result = await _repository.Entities.Where(where).ToListAsync();
            }
            return result;
        }

        /// <summary>
        /// 根据条件获取文件清单信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<FileInventoryEntity> GetFileInventoryInfoAsync(Expression<Func<FileInventoryEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _mongoDbRepository.GetAsync(_collection, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _repository.FirstOrDefaultAsync(where);
            return entity;
        }
      
        /// <summary>
        /// 获取文件清单数据
        /// </summary>
        /// <param name="organizeId">组织id</param>
        /// <param name="mechanismId">机构id</param>
        /// <param name="ids">文件清单id集合</param>
        /// <returns></returns>
        private async Task<List<FileInventoryEntity>> GetFileInventoryListAsync
            (string organizeId,string mechanismId ,List<string> ids)
        {
            Expression<Func<FileInventoryEntity, bool>> where = m =>m.DeleteMark == null;
            if (!string.IsNullOrWhiteSpace(organizeId)) where = where.And(m=>m.OrganizeId== organizeId);
            if (!string.IsNullOrWhiteSpace(mechanismId) && !mechanismId.Contains(","))
            {
                string queryMechanismId = await _mechanismService.GetIdAsync(mechanismId, organizeId);
                where = where.And(m => m.MechanismId == queryMechanismId);
            }
            if (ids.Any()) where = where.And(m=>ids.Contains(m.Id));
            //从从mongodb中获取
            var result= await _mongoDbRepository.GetListAsync(_collection, where);
            if (!result.Any())
            {
                //再从sqlserver中获取
                result = await _repository.Entities.Where(where).ToListAsync();
            }
            return result;
        }
        #endregion

        #region 工作记录       
        /// <summary>
        /// 分页获取工作记录数据
        /// </summary>
        /// <param name="query">查询工作记录请求模型</param>
        /// <returns></returns>
        [HttpPost("workrecord/gets")]
        public async Task<TkPageResult<WorkRecordListDto>> Gets([FromBody] QueryWorkRecordFilterRequestModel query)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;
                string roleId = user.Subject.FindFirst(ClaimConst.ROLEID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;

                #region 组装查询条件
                Expression<Func<WorkRecordsEntity, bool>> where = m =>
               m.DeleteMark == null && (m.CreatorUserId == userId ||
               (m.SharedScope == 0 && m.OrganizeId == organizeId && m.EnabledMark == 1) ||
               (m.SharedScope == 1 && m.MechanismId == mechanismId && m.EnabledMark == 1) ||
               (m.SharedScope == 2 && m.SharedScopeValue.Contains(roleId) && m.EnabledMark == 1) ||
               (m.SharedScope == 3 && m.SharedScopeValue.Contains(userId) && m.EnabledMark == 1));

                if (query.enabledMark == 1) where = where.And(m => m.EnabledMark == 1);
                if (query.enabledMark == 0) where = where.And(m => m.EnabledMark != 1);
                if (!string.IsNullOrWhiteSpace(query.organizeId))
                    where = where.And(m => m.OrganizeId == query.organizeId);
                if (!string.IsNullOrWhiteSpace(query.mechanismId))
                {
                    string queryMechanismId = await _mechanismService.GetIdAsync(query.mechanismId, organizeId);
                    where = where.And(m => m.MechanismId == queryMechanismId);
                }
                if (!string.IsNullOrWhiteSpace(query.classifyId))
                {
                    string queryClassifyId = await _dictionaryService.GetIdAsync(query.classifyId, organizeId);
                    where = where.And(m => m.ClassifyId == queryClassifyId);
                }
                if (query.sharedScope != null)
                    where = where.And(m => m.SharedScope == query.sharedScope.GetHashCode());
                if (query.startTime != null) where = where.And(m => m.CreatorTime >= query.startTime);
                if (query.endTime != null) where = where.And(m => m.CreatorTime <= query.endTime);
                if (!string.IsNullOrWhiteSpace(query.keyword))
                    where = where.And(m => m.Title.Contains(query.keyword));
                #endregion

                var pageList = new SqlSugarPagedList<WorkRecordListDto>();
                #region 从先mongodb中获取工作记录数据
                //排序生成器
                var builderSort = Builders<WorkRecordsEntity>.Sort;
                //排序约束   Ascending 正序    Descending 倒序
                var sort = builderSort.Ascending(r => r.SortCode).Descending(r => r.CreatorTime);
                //Item1.结果集 Item2.总条数 Item3.总页数
                (List<WorkRecordsEntity>, int, int) result =
                    await _workMongoDbRepository.GetListAsync(_work,
                    where, query.currentPage, query.pageSize, null, sort);
                pageList.list = result.Item1.Adapt<List<WorkRecordListDto>>();
                pageList.pagination = new PagedModel()
                {
                    PageIndex = query.currentPage,
                    PageSize = query.pageSize,
                    Total = result.Item2,
                    PageCount = result.Item3
                };
                #endregion

                if (!pageList.list.Any())
                {
                    #region 再从sqlserver中获取工作记录数据
                    var sqlResult = await _workRepository.Entities.Where(where)
                        .OrderBy(r => r.SortCode, OrderByType.Asc)
                        .OrderBy(r => r.CreatorTime, OrderByType.Desc)
                        .ToPagedListAsync(query.currentPage, query.pageSize);
                    pageList.list = sqlResult.list.Adapt<List<WorkRecordListDto>>();
                    pageList.pagination = sqlResult.pagination;
                    #endregion
                }

                #region 处理工作记录返回数据
                if (pageList.list.Any())
                {
                    var orgIds = pageList.list.Select(r => r.organizeId).Distinct().ToList();
                    var orgs = await _organizeService.GetOrganizeListByIds(orgIds);
                    var mechanismIds = pageList.list.Where(r => !string.IsNullOrWhiteSpace(r.mechanismId))
                        ?.Select(r => r.mechanismId.Split(',').ToList())
                        ?.SelectMany(r => r).Distinct().ToList();
                    var mechanisms = !mechanismIds.Any() ? new List<MechanismEntity>() :
                        await _mechanismService.GetMechanismListAsync(null, mechanismIds);
                    var classifyIds = pageList.list.Select(r => r.classifyId.Split(',').ToList())
                       .SelectMany(r => r).Distinct().ToList();
                    var classifys = await _dictionaryService.GetDictionaryListByIds(classifyIds);
                    var userIds = pageList.list.Select(r => r.creatorUserId).Distinct().ToList();
                    var users = await _tkUsersService.GetUserListByIds(userIds);
                    var workItemIds= pageList.list.Select(r => r.workItemId).Distinct().ToList();
                    var workItems = await GetFileInventoryListAsync("","", workItemIds);
                    pageList.list.ForEach(record =>
                    {
                        record.sharedScopeText = EnumHelper.GetEnumDescriptionString
                        (record.sharedScope, typeof(SharedScopeEnum));
                        if (!string.IsNullOrWhiteSpace(record.organizeId))
                            record.organizeName = orgs?.FirstOrDefault(r => r.Id == record.organizeId)?.FullName;
                        if (!string.IsNullOrWhiteSpace(record.mechanismId))
                        {
                            record.mechanismName = mechanisms?.FirstOrDefault(r=>r.Id==record.mechanismId.Split(',').Last())?.Name;
                           
                        }
                        if (!string.IsNullOrWhiteSpace(record.classifyId))
                        {
                            record.classifyName = classifys?.FirstOrDefault(r => r.Id == record.classifyId.Split(',').Last())?.Name;
                        }
                        record.creatorUserName = users?.FirstOrDefault(r => r.Id == record.creatorUserId)?.RealName;
                        record.workItem = workItems?.FirstOrDefault(r => r.Id == record.workItemId)?.WorkItem;
                    });
                }
                #endregion

                return TkPageResult<WorkRecordListDto>.Success(pageList);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"分页获取工作记录数据发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 获取工作记录详细信息
        /// </summary>
        /// <param name="id">工作记录id</param>
        /// <returns></returns>
        [HttpPost("workrecord/get/{id}")]
        public async Task<TkResult<WorkRecordInfoDto>> Get([Required] string id)
        {
            try
            {
                var entity = await GetWorkRecordInfoAsync(r => r.Id == id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Record0018);

                var record = entity.Adapt<WorkRecordInfoDto>();
                #region 处理工作记录返回信息
                record.sharedScopeText = EnumHelper.GetEnumDescriptionString
                        (record.sharedScope, typeof(SharedScopeEnum));
                if (!string.IsNullOrWhiteSpace(record.organizeId) && record.organizeId != "org00000000")
                    record.organizeName = (await _organizeService.GetOrganizeListByIds
                            (new List<string>() { record.organizeId }))?[0].FullName;
                if (!string.IsNullOrWhiteSpace(record.mechanismId) && record.mechanismId != "jg000000")
                {
                    record.mechanismName = string.Join('/', (await _mechanismService
                        .GetMechanismListAsync(null, record.mechanismId.Split(',').ToList()))
                        ?.Select(r => r.Name)?.ToList());
                }
                if (!string.IsNullOrWhiteSpace(record.classifyId))
                {
                    record.classifyName = string.Join('/', (await _dictionaryService
                   .GetDictionaryListByIds(record.classifyId.Split(',').ToList()))
                   ?.Select(r => r.Name)?.ToList());
                }
                #region 处理共享范围
                if (!string.IsNullOrWhiteSpace(record.sharedScopeValue))
                {
                    //共享范围(0.全组织 1.特定机构 2.特定角色 3.特定用户 4.仅自己可见)
                    switch (record.sharedScope)
                    {
                        case 0:
                            record.sharedScopeValueText = "全组织";
                            break;
                        case 1:
                            var dic = await _mechanismService.GetIdsAsync(record.sharedScopeValue.Split(',').ToList(), record.organizeId);
                            var values = dic.Values.ToList();
                            record.sharedScopeValueText = string.Join(',', values.Select(r => r.Item2).ToList());
                            record.sharedScopeMechanismValue = values.Select(r => r.Item1.Split(',').ToArray())?.ToList();
                            break;
                        case 2:
                            record.sharedScopeValueText = string.Join(',', (await _tkRoleService
                                .GetTkRoleListByIdsAsync(record.sharedScopeValue.Split(',').ToList()))
                                ?.Select(r => r.Name)?.ToList());
                            break;
                        case 3:
                            record.sharedScopeValueText = string.Join(',', (await _tkUsersService
                               .GetUserListByIds(record.sharedScopeValue.Split(',').ToList()))
                               ?.Select(r => r.RealName)?.ToList());
                            break;
                        case 4:
                            record.sharedScopeValueText = "仅自己可见";
                            break;
                    }
                }
                #endregion
                if (!string.IsNullOrWhiteSpace(record.creatorUserId))
                    record.creatorUserName = (await _tkUsersService.GetUserInfoByUserId(record.creatorUserId))?.RealName;
                record.workItem = (await GetFileInventoryInfoAsync(m => m.Id == record.workItemId && m.DeleteMark == null))?.WorkItem;
                #endregion

                //获取工作记录相关附件数据
                var fileData = await GetWorkRecordFilesListAsync(id);
                record.fileData = fileData.Adapt<List<CommonFileListDto>>();
                //获取工作记录动态字段配置数据
                var dynamicData = await GetWorkRecordDynamicFieldsListAsync(id);
                record.dynamicData = dynamicData.Adapt<List<CommonDynamicFieldListDto>>();
                if (record.dynamicData.Any())
                {
                    record.dynamicData.ForEach(dynamic => {
                        dynamic.fieldTypeText = EnumHelper.GetEnumDescriptionString
                        (dynamic.fieldType, typeof(DynamicFieldTypeEnum));
                    });
                }

                #region 累加浏览次数
                entity.ViewCount++;
                await _workRepository.Context.Updateable(entity)
                    .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                await _workMongoDbRepository.UpdateAsync(entity, _work, m => m.Id == entity.Id);
                #endregion

                return TkResult<WorkRecordInfoDto>.Success(record);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"获取文件记录详细信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 添加工作记录信息
        /// </summary>
        /// <param name="input">添加工作记录请求模型</param>
        /// <returns></returns>
        [HttpPost("workrecord/add")]
        public async Task Add([FromBody] AddWorkRecordRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);
                if ((await GetWorkRecordInfoAsync(r => r.OrganizeId == organizeId && r.ClassifyId == input.classifyId &&
                r.MechanismId == mechanismId && r.WorkItemId==input.workItemId && r.Title == input.title && r.DeleteMark == null)) != null)
                    throw YNTKException.Oh(ErrorCode.Record0015);

                var entity = input.Adapt<WorkRecordsEntity>();
                entity.SharedScope = input.sharedScope.GetHashCode();
                entity.OrganizeId = organizeId;
                entity.MechanismId = mechanismId;

                //保存工作记录到sqlserver
                var isOk = await _workRepository.Context.Insertable(entity)
                   .CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
                _ = isOk ?? throw YNTKException.Oh(ErrorCode.Record0016);

                //保存工作记录到mongodb
                 entity = isOk;
                var result = await _workMongoDbRepository.AddAsync(entity, _work);
                if (!result) throw YNTKException.Oh(ErrorCode.Record0017);

                //保存工作记录相关附件
                await SaveWorkRecordFilesAsync(entity, input.fileData);
                //保存工作记录动态字段
                await SaveWorkRecordDynamicFieldsAsync(entity, input.dynamicData);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"添加工作记录信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 修改工作记录信息
        /// </summary>
        /// <param name="input">修改工作记录请求模型</param>
        /// <returns></returns>
        [HttpPut("workrecord/update")]
        public async Task Update([FromBody] UpdateWorkRecordRequestModel input)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                string organizeId = user.Subject.FindFirst(ClaimConst.ORGANIZEID).Value;
                string mechanismId = user.Subject.FindFirst(ClaimConst.MECHANISMID).Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetWorkRecordInfoAsync(r => r.Id == input.id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Record0018);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);
                if ((await GetWorkRecordInfoAsync(r => r.OrganizeId == organizeId && r.ClassifyId == input.classifyId &&
                r.MechanismId == mechanismId && r.WorkItemId == input.workItemId && r.Title == input.title && 
                r.Id!=input.id && r.DeleteMark == null)) != null) throw YNTKException.Oh(ErrorCode.Record0015);

                entity = input.Mapper(entity);
                entity.SharedScope = input.sharedScope.GetHashCode();
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;

                //保存工作记录到sqlserver
                var isOK = await _workRepository.Context.Updateable(entity)
               .IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
                if (!(isOK > 0)) throw YNTKException.Oh(ErrorCode.Record0019);

                //保存工作记录到mongodb
                var update = await _workMongoDbRepository.UpdateAsync(entity, _work, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Record0020);

                //保存工作记录相关附件
                await SaveWorkRecordFilesAsync(entity, input.fileData);
                //保存工作记录动态字段
                await SaveWorkRecordDynamicFieldsAsync(entity, input.dynamicData);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"修改工作记录信息发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除工作记录
        /// </summary>
        /// <param name="id">工作记录id</param>
        /// <returns></returns>
        [HttpDelete("workrecord/delete/{id}")]
        public async Task Delete([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetWorkRecordInfoAsync(r => r.Id ==id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Record0018);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //从sqlserver中删除
                var isOk = await _workRepository.Context.Deleteable(entity).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Record0021);

                //从mongodb中删除
                var delete = await _workMongoDbRepository.DeleteAsync(_work, m => m.Id == id);
                if (!(delete > 0)) throw YNTKException.Oh(ErrorCode.Record0022);

                //删除工作记录相关附件
                await DeleteWorkRecordFilesAsync(id);
                //删除工作记录动态字段数据
                await DeleteWorkRecordDynamicFieldsAsync(id);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"删除工作记录发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新工作记录状态(启用/禁用)
        /// </summary>
        /// <param name="id">工作记录id</param>
        /// <returns></returns>
        [HttpPut("workrecord/state/{id}")]
        public async Task UpdateState([Required] string id)
        {
            try
            {
                var user = _httpContext.User.FindFirst(ClaimConst.CLAINM_USERID);
                string userId = user.Value;
                //账号类型【0.平台运营人员 1.超级管理员 2.组织管理员 3.组织用户 4.第三方登录用户 5.游客用户】
                var authenticationType = user.Subject.FindFirst(ClaimConst.ACCOUNTTYPE).Value;
                if (authenticationType == "4" || authenticationType == "5")
                    throw YNTKException.Oh(ErrorCode.D1016);

                var entity = await GetWorkRecordInfoAsync(r => r.Id == id && r.DeleteMark == null);
                _ = entity ?? throw YNTKException.Oh(ErrorCode.Record0018);
                if (entity.CreatorUserId != userId) throw YNTKException.Oh(ErrorCode.D1016);

                //sqlserver更新工作记录状态
                var isOk = await _workRepository.Context.Updateable<WorkRecordsEntity>()
               .SetColumns(it => new WorkRecordsEntity()
               {
                   EnabledMark = SqlFunc.IIF(it.EnabledMark == 1, 0, 1),
                   LastModifyUserId = userId,
                   LastModifyTime = SqlFunc.GetDate()
               }).Where(it => it.Id == id).ExecuteCommandAsync();
                if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Record0023);

                //mongodb更新工作记录状态
                entity.EnabledMark = entity.EnabledMark == 1 ? 0 : 1;
                entity.LastModifyTime = DateTime.Now;
                entity.LastModifyUserId = userId;
                var update = await _workMongoDbRepository.UpdateAsync(entity, _work, m => m.Id == entity.Id);
                if (!(update.ModifiedCount > 0)) throw YNTKException.Oh(ErrorCode.Record0024);
            }
            catch (Exception ex)
            {
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"更新工作记录状态(启用/禁用)发生异常：{ex.Message}");
            }
        }




        /// <summary>
        /// 根据条件获取工作记录信息
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        private async Task<WorkRecordsEntity> GetWorkRecordInfoAsync(Expression<Func<WorkRecordsEntity, bool>> where)
        {
            //从从mongodb中获取
            var entity = await _workMongoDbRepository.GetAsync(_work, where);
            //再从sqlserver中获取
            if (entity == null) entity = await _workRepository.FirstOrDefaultAsync(where);
            return entity;
        }
        #endregion

        #region 工作记录相关附件
        /// <summary>
        /// 获取工作记录相关附件数据
        /// </summary>
        /// <param name="workRecordId">工作记录id</param>
        /// <returns></returns>
        private async Task<List<WorkRecordFilesEntity>> GetWorkRecordFilesListAsync(string workRecordId)
        {
            //从mongodb中获取附件数据
            var result = await _fileMongoDbRepository.GetListAsync(_files, r => r.WorkRecordId == workRecordId);
            if (!result.Any())
            {
                //从sqlserver数据库中获取附件数据
                result = await _fileRepository.Entities
                    .Where(r => r.WorkRecordId == workRecordId).ToListAsync();
            }
            return result;
        }

        /// <summary>
        /// 保存工作记录相关附件
        /// </summary>
        /// <param name="entity">工作记录信息</param>
        /// <param name="fileData">附件数据</param>
        /// <returns></returns>
        private async Task SaveWorkRecordFilesAsync(WorkRecordsEntity entity,List<CommonFileRequestModel> fileData)
        {
            try
            {
                _fileRepository.Ado.BeginTran();
                //删除原数据
                await _fileMongoDbRepository.DeleteAsync(_files, r => r.WorkRecordId == entity.Id);
                await _fileRepository.DeleteAsync(r => r.WorkRecordId == entity.Id);
                if (fileData != null && fileData.Count > 0)
                {
                    var files = new List<WorkRecordFilesEntity>();
                    var file = new WorkRecordFilesEntity();
                    fileData.ForEach(item =>
                    {
                        file = item.Adapt<WorkRecordFilesEntity>();
                        file.Id = YitIdHelper.NextId().ToString();
                        file.OrganizeId = entity.OrganizeId;
                        file.MechanismId = entity.MechanismId;
                        file.WorkRecordId = entity.Id;
                        file.CreatorUserId = entity.CreatorUserId;
                        file.CreatorTime = entity.CreatorTime;
                        files.Add(file);
                    });
                    //保存到sqlserver                 
                    var isOk = await _fileRepository.Context.Insertable(files).ExecuteCommandAsync();
                    if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Record0011);
                    //保存到mongodb
                    var succeed = await _fileMongoDbRepository.AddListAsync(files, _files);
                    if (!succeed) throw YNTKException.Oh(ErrorCode.Record0012);
                }
                _fileRepository.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                _fileRepository.Ado.RollbackTran();
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"保存工作记录相关附件发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除工作记录相关附件数据
        /// </summary>
        /// <param name="workRecordId">工作记录id</param>
        /// <returns></returns>
        private async Task DeleteWorkRecordFilesAsync(string workRecordId)
        {
            var result = await GetWorkRecordFilesListAsync(workRecordId);
            if (result.Any())
            {
                //删除原数据
                await _fileMongoDbRepository.DeleteAsync(_files, r => r.WorkRecordId == workRecordId);
                await _fileRepository.DeleteAsync(r => r.WorkRecordId == workRecordId);
                //删除文件
                var deleteFiles = result.Adapt<List<FileListDto>>();
                _fileService.DeleteFiles(deleteFiles);
            }
        }
        #endregion

        #region 工作记录动态字段
        /// <summary>
        /// 获取工作记录动态字段数据
        /// </summary>
        /// <param name="workRecordId">工作记录id</param>
        /// <returns></returns>
        private async Task<List<WorkRecordDynamicFieldsEntity>> GetWorkRecordDynamicFieldsListAsync(string workRecordId)
        {
            //从mongodb中获取动态字段数据
            var result = await _dynamicMongoDbRepository.GetListAsync(_dynamic, r => r.WorkRecordId == workRecordId);
            if (!result.Any())
            {
                //从sqlserver数据库中获取动态字段数据
                result = await _dynamicRepository.Entities
                    .Where(r => r.WorkRecordId == workRecordId).ToListAsync();
            }
            return result;
        }

        /// <summary>
        /// 保存工作记录动态字段
        /// </summary>
        /// <param name="entity">工作记录信息</param>
        /// <param name="fieldData">动态字段数据</param>
        /// <returns></returns>
        private async Task SaveWorkRecordDynamicFieldsAsync(WorkRecordsEntity entity,
            List<CommonDynamicFieldsRequestModel> fieldData)
        {
            try
            {
                _dynamicRepository.Ado.BeginTran();
                //删除原数据
                await _dynamicMongoDbRepository.DeleteAsync(_dynamic, r => r.WorkRecordId == entity.Id);
                await _dynamicRepository.DeleteAsync(r => r.WorkRecordId == entity.Id);
                if (fieldData != null && fieldData.Count > 0)
                {
                    var fields = new List<WorkRecordDynamicFieldsEntity>();
                    var field = new WorkRecordDynamicFieldsEntity();
                    fieldData.ForEach(item =>
                    {
                        field = item.Adapt<WorkRecordDynamicFieldsEntity>();
                        field.Id = YitIdHelper.NextId().ToString();
                        field.OrganizeId = entity.OrganizeId;
                        field.MechanismId = entity.MechanismId;
                        field.WorkRecordId = entity.Id;
                        field.CreatorUserId = entity.CreatorUserId;
                        field.CreatorTime = entity.CreatorTime;
                        fields.Add(field);
                    });
                    //保存到sqlserver                 
                    var isOk = await _dynamicRepository.Context.Insertable(fields).ExecuteCommandAsync();
                    if (!(isOk > 0)) throw YNTKException.Oh(ErrorCode.Record0013);
                    //保存到mongodb
                    var succeed = await _dynamicMongoDbRepository.AddListAsync(fields, _dynamic);
                    if (!succeed) throw YNTKException.Oh(ErrorCode.Record0014);
                }
                _dynamicRepository.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                _dynamicRepository.Ado.RollbackTran();
                if (ex.Message.Contains("[")) throw YNTKException.Oh($"{ex.Message}");
                throw YNTKException.Oh($"保存工作记录动态字段发生异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 删除工作记录动态字段数据
        /// </summary>
        /// <param name="workRecordId">工作记录id</param>
        /// <returns></returns>
        private async Task DeleteWorkRecordDynamicFieldsAsync(string workRecordId)
        {
            var result = await GetWorkRecordDynamicFieldsListAsync(workRecordId);
            if (result.Any())
            {
                //删除原数据
                await _dynamicMongoDbRepository.DeleteAsync(_dynamic, r => r.WorkRecordId == workRecordId);
                await _dynamicRepository.DeleteAsync(r => r.WorkRecordId == workRecordId);
            }
        }
        #endregion

    }
}
